package top.itbook;


import top.itbook.pojo.User;
import top.itbook.shop.Armor;
import top.itbook.shop.Arms;
import top.itbook.shop.ShopArmor;
import top.itbook.shop.ShopArms;
import top.itbook.util.Run;
import top.itbook.util.SHA256;
import top.itbook.util.scanner.InputInt;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 用户菜单
 */
public class UserMenu {
    public static void menu(User user, SHA256 sha256, ArrayList<Arms> armsShop, ArrayList<Armor> armorShop) {
        // TODO: 2022/5/28 后续有了数据库即写入排行榜，每天进行刷新本地缓存 可自行开发一下哦 ~
        while (true) {
            System.out.println("****************************************");
            System.out.println("1.打印玩家信息");
            System.out.println("2.修改账户密码");
            System.out.println("3.访问系统商城");
            System.out.println("4.进入地图探险");
            System.out.println("5.学习灵术知识");
            System.out.println("6.当前运行信息");
            System.out.println("7.退出游戏登录");
            System.out.println("****************************************");
            System.out.print("请输入您的选择：");
            int index = InputInt.obtainInput();
            switch (index) {
                case 1: // 打印玩家信息
                    userInformation(user);
                    break;
                case 2: // 修改密码
                    changePassword(new Scanner(System.in),user,sha256);
                    break;
                case 3: // 访问系统商城
                    systemMall(new Scanner(System.in),armsShop,user,armorShop);
                    break;
                case 4: // 进入地图探险
                    map(new Scanner(System.in), user);
                case 5: // 学习灵术知识
                    break;
                case 6: // 查看当前运行信息
                    Run.getINFO();
                    break;
                case 7: // 退出登录
                    System.out.println("是否将这次信息保存至本地，这将替换上一次保存的信息（Y\\N）：");
                    Scanner scanner = new Scanner(System.in);
                    String s = scanner.next();
                    if (s.equals("Y") || s.equals("y")){
                        File file = new File("C:\\GamesDemo");
                        ObjectOutputStream outputStream = null;
                        // 检测本地目录是否存在，若不存在则创建目录
                        if (file.exists() == false){
                            // 文件不存在，开始创建本地缓存
                            file.mkdir();
                        }
                        // 将这一次的用户信息进行本地缓存
                        // 使用对象字节输出流包装字节输出流管道
                        try {
                            outputStream = new ObjectOutputStream(new FileOutputStream(Main.USER_FILE));
                            // 调用对象序列化方法
                            outputStream.writeObject(user);
                        } catch (IOException e) {
                            e.printStackTrace();
                            System.err.println("本地对象缓存失败，建议联系软件开发者进行反馈。");
                        }finally{
                            // 释放管道资源
                            try {
                                outputStream.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                                System.out.println("管道资源释放失败，建议您重启软件并将错误上报至开发者！");
                            }
                        }
                    }
                    System.out.println("用户：" + user.getUsername() + "退出了游戏~");
                    return; // 终结方法
                default:
                    System.out.println("对不起，您的输入有误，请重新输入~");
            }
        }
    }

    /**
     * 打印玩家信息
     *
     * @param user 已登录的用户
     */
    private static void userInformation(User user) {
        InetAddress net = null;
        try {
            net = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        System.out.println("****************************************");
        System.out.println("用户名：" + user.getUsername());
        // 获取到的是十六进制，而1位十六进制是4比特，也就是字符串总长度 * 4也就是比特位
        System.out.println("当前安全算法强度：" + user.getPassword().length() * 4 + " 位（比特）");
        // assert net != null; // 关于防止出现net == null情况这里不推荐使用断言进行判断
        if (net != null) {
            System.out.println("当前IP（大多为局域网IP）：" + net.getHostAddress());
        }
        System.out.println("注册时间：" + user.getRegistrationDate());
        if (user.getWeaponBar() != null) {
            System.out.println("主武器：" + user.getWeaponBar().getName());
        }else{
            System.out.println("主武器：无。");
        }
        if (user.getArmourFence() != null){
            System.out.println("防具：" + user.getArmourFence().getName());
        }else{
            System.out.println("防具：无。");
        }
        System.out.println("等级：" + user.getGrade());
        System.out.println("金币：" + user.getGold());
        System.out.println("点券：" + user.getCountingCoupons());
        System.out.println("血量：" + user.getBlood());
        System.out.println("攻击：" + user.getAttack());
        System.out.println("防御：" + user.getDefense());
        System.out.println("灵力：" + user.getMana());
        System.out.println("****************************************");
    }

    /**
     * 系统商城购物中心
     */
    private static void systemMall(Scanner scanner, ArrayList<Arms> armsArrayList,User user,ArrayList<Armor> armorArrayList) {
        while (true) {
            System.out.println("****************************************");
            System.out.println("1、随机事件\t\t\t1点券 - 勿选，开发中");
            System.out.println("2、改名卡\t\t\t5点券");
            System.out.println("3、等级提升5级\t\t\t2点券 - 勿选，开发中");
            System.out.println("4、系统武器商城");
            System.out.println("5、系统防具商城");
            System.out.println("****************************************");
            System.out.print("请输入序号查看详情：");
            // 获取用户输入的序号
            int index = InputInt.obtainInput();
            switch (index) {
                case 1: // 随机事件
                    break;
                case 2: // 改名卡
                    System.out.println("******************************");
                    System.out.println("道具名称：改名卡");
                    System.out.println("道具价格：50金币");
                    System.out.println("道具介绍：可修改一次游戏名，购买后立即生效！");
                    System.out.println("******************************");
                    System.out.print("请问您是否要购买（Y/N）：");
                    String indexString = scanner.next();
                    scanner = new Scanner(System.in);
                    if (indexString.equals("y") || indexString.equals("Y")){
                        // 判断余额是否足够
                        if (user.getGold() < 50){
                            System.out.println("对不起，您的金币余额不足，您还剩：" + user.getGold());
                            return;
                        }else{
                            user.setGold(user.getGold() - 50);
                            System.out.println("购买成功，本次扣款 50 金币");
                            while (true) {
                                System.out.println("请输入您要修改的姓名：");
                                String setName = scanner.next();
                                System.out.print("您确定要将您的用户名改为： " + setName + " 吗？（Y/N）");
                                scanner = new Scanner(System.in);
                                indexString = scanner.next();
                                if (indexString.equals("Y") || indexString.equals("y")){
                                    user.setUsername(setName);
                                    System.out.println("修改成功，您的新用户名已修改为：" + user.getUsername());
                                    return;
                                }else{
                                    continue;
                                }
                            }
                        }
                    }else{
                        System.out.println("欢迎您下次访问系统商店 ~");
                        return;
                    }
                    // break;
                case 3: // 等级提升5级
//                    System.out.println("******************************");
//                    System.out.println("道具名称：等级提升卡");
//                    System.out.println("道具价格：1点券");
//                    System.out.println("道具介绍：可使玩家等级立即提升5级，购买后即刻生效！");
//                    System.out.println("******************************");
//                    System.out.print("请问您是否要购买（Y/N）：");
                    break;
                case 4: // 系统武器商城
                    SystemArmsShop(armsArrayList,user);
                    return;
                case 5: // 系统防具商城
                    SystemArmorShop(armorArrayList,user);
                    return;
                default:
                    break;
            }
        }
    }

    private static void SystemArmorShop(ArrayList<Armor> armorArrayList,User user) {
        boolean length = false;

        if (armorArrayList == null){
            System.err.println("警告：SystemArmorShop方法传入空值！系统自动终结对应方法执行！");
            return;
        }
        if (armorArrayList.size() == 0){
            System.out.println("当前系统商店中不存在任何商品，请添加后查看！");
            return;
        }
        // 查看是否存在商品但全都是未上架状态防止出现什么商品都没打印还让用户输入要购买的商品的情况
        for (Armor armor : armorArrayList) {
            if (armor.getState()){
                length = true; // 为true则证明最少有一个商品为上架状态
                break; // 找到一个上架的商品后目的就已经达到了，不需要继续循环下去
            }
        }
        if (length == false){
            System.out.println("对不起，防具商城中不存在任何防具或已有防具但是却都是未上架状态，请检查！");
            return; // 终结方法的执行
        }
        // 遍历所有商品
        for (Armor armor : armorArrayList) {
            if (armor.getState()){
                ShopArmor shopArmor = new ShopArmor();
                shopArmor.getArmor(armor); // 打印商品信息
            }
        }
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入您要购买的商品名：");
        String armorName = scanner.next();
        for (Armor armor : armorArrayList) {
            if (armor.getName().equals(armorName)){
                System.out.println("您要购买的武器为：" + armor.getName() + "。您将花费金币：" + armor.getMoney());
                System.out.println("请确认是否购买(Y/N)：");
                scanner = new Scanner(System.in);
                String confirm = scanner.next();
                if (confirm.equals("Y") || confirm.equals("y")){
                    if (user.getGold() < armor.getMoney()){
                        System.out.println("对不起，您的余额不足，请继续努力冒险赚钱去吧！");
                        return;
                    }else{
                        user.setGold(user.getGold() - armor.getMoney());
                        user.setDefense(user.getDefense() + armor.getDefense());
                        user.setArmourFence(armor);
                        System.out.println("恭喜您，您成功的购买了【" + armor.getName() + "】花费了：" + armor.getMoney() + "金币");
                    }
                }else{
                    System.out.println("欢迎您下次再来！");
                    return;
                }
            }
        }
        System.out.println("对不起，系统中没有找到您想要的商品！请重新检查 ~");
        return; // 建议勿删，保留代码可读性 ！
    }

    /**
     * 地图
     *
     * @param scanner 键盘扫描器
     */
    public static void map(Scanner scanner, User user) {
        Random random = new Random(); // 随机数生成器
        System.out.println("****************************************");
        System.out.println("1.前往城市中心探险（初级）");
        System.out.println("2.前往阴阳小镇探险（初级）");
        System.out.println("3.前往魔鬼城探险（中级）");
        System.out.println("4.前往武士城探险（中级）");
        System.out.println("5.前往邪恶城堡探险（高级）");
        System.out.println("****************************************");
        System.out.print("请输入对应序号：");
        // 给while打个标签以直接break出while而不是内层的switch
        // TODO: 2022/6/4 建议扩展每次扣血前判断血量是否足够扣除，若不够则判定为死亡，即游戏结束
        mmp:
        while (true) {
            // 生成随机数
            int r = random.nextInt(4) + 1;
            int index = InputInt.obtainInput();
            switch (index) {
                case 1: // 前往城市中心探险
                    if (r == 1) {
                        System.out.println("恭喜您，走在大马路上看见地上有个纸币，捡起来一看是10元。");
                        user.setGold(user.getGold() + 10);
                    }
                    if (r == 2) {
                        if (user.getDefense() < 60) {
                            System.out.println("你走进了商业区，不注意间，你的钱包里的一些钱不见了。损失50元。");
                            user.setGold(user.getGold() - 50);
                        }
                        if (user.getDefense() >= 60) {
                            System.out.println("你在商业区散步，一个《不小心》的回头发现一个小偷正在顺走你的钱包，你反手一个《大比斗》将其拿下。防御值+10,攻击值+15");
                            user.setDefense(user.getDefense() + 10);
                            user.setAttack(user.getAttack() + 15);
                        }
                    }
                    if (r == 3) {
                        while (true) { // 这个循环是防止有人没有按要求输入Y或N
                            System.out.print("路过书店，请选择是否花费10金币进入（Y\\N）：");
                            String choice = scanner.next();
                            if (choice.equals("Y") || choice.equals("y")) { // 进入书店
                                if (user.getGold() < 10) {
                                    // 钱数不足进入书店
                                    System.out.println("对不起，您的金币余额不足，您还有：" + user.getGold() + " 金币。");
                                    return; // 终结方法
                                } else {
                                    System.out.println("1.学习防御相关知识");
                                    System.out.println("2.学习攻击相关知识");
                                    System.out.println("3.学习灵力相关知识");
                                    System.out.print("请选择学习的相关知识（输错默认放弃本次机会）：");
                                    int study = InputInt.obtainInput();
                                    if (study == 1) { // 学习防御相关知识
                                        // 扣除10金币
                                        user.setGold(user.getGold() - 10);
                                        System.out.println("你学习到了关于防御方面的知识（防御+10）");
                                        user.setDefense(user.getDefense() + 10);
                                        return;
                                    } else if (study == 2) { // 学习攻击相关知识
                                        // 扣除10金币
                                        user.setGold(user.getGold() - 10);
                                        System.out.println("你学习到了关于攻击方面的知识（攻击+10）");
                                        user.setAttack(user.getAttack() + 10);
                                        return;
                                    } else if (study == 3) { // 学习灵力相关知识
                                        // 扣除10金币
                                        user.setGold(user.getGold() - 10);
                                        System.out.println("你学习到了关于灵力方面的知识（灵力+10）");
                                        user.setMana(user.getMana() + 10);
                                        return;
                                    }
                                }
                            } else if (choice.equals("N") || choice.equals("n")) { // 走过
                                System.out.println("您站在门口思考了些许，并继续往其他地方走去~");
                                return; // 终结方法
                            } else {
                                System.out.println("您输入的不正确，请检查后重新输入");
                            }
                        }
                    }
                    if (r == 4) {
                        System.out.println("你逛了一整天，什么收获也没有~");
                    }
                    break mmp;
                case 2: // 前往阴阳小镇探险
                    if (r == 1) {
                        System.out.println("被一伙人拦下，被迫参战~");
                        System.out.println("扣除血量：5 获得攻击值：1");
                        user.setBlood(user.getBlood() - 5);
                        user.setAttack(user.getAttack() + 1);
                        return;
                    }
                    if (r == 2){
                        System.out.println("进入修炼所修炼，灵力提升 + 5");
                        user.setMana(user.getMana() + 10);
                        return;
                    }
                    if (r == 3){
                        System.out.println("走了一天，什么都没发生~");
                        return;
                    }
                    if (r == 4) {
                        System.out.println("进入修炼场修炼，攻击提升 + 5");
                        user.setAttack(user.getAttack() + 5);
                    }
                    return;
                case 3: // 前往魔鬼城探险
                    if (r == 1){
                        System.out.println("遭遇城堡守卫，被迫迎战！");
                        // 如果攻击大于等于40并且防御大于等于60则胜利
                        if (user.getAttack() >= 40 && user.getDefense() >= 60){
                            System.out.println("但是对于你而言这只是小cass，轻松解决~");
                            // 等级 + 1
                            user.setGrade(user.getGrade() + 1);
                            return;
                        }
                        if (user.getAttack() <= 39 && user.getDefense() <= 59){
                            System.out.println("很遗憾，你完全落败，需要养伤。血量 - 30");
                            user.setBlood(user.getBlood() - 30);
                            return; // 终结方法顺带防止下一个if被执行
                        }
                        if (user.getAttack() <= 39 || user.getDefense() <= 59){
                            System.out.println("很不幸，您在激烈战斗中受伤，勉强胜利~ 血量 - 5 攻击提升10 防御提升20");
                            user.setBlood(user.getBlood() - 5);
                            user.setAttack(user.getAttack() + 10);
                            user.setDefense(user.getDefense() + 20);
                            return; // 终结方法
                        }
                    }
                    if (r == 2){
                        System.out.println("一路上静悄悄的斩杀不知名的小怪，获得等级提升 + 1");
                        user.setGrade(user.getGrade() + 1);
                        return;
                    }
                    if (r == 3){
                        System.out.println("一路上很安静，什么也没有发生~");
                        return;
                    }
                    if (r == 4){
                        System.out.println("发现魔鬼城守城将军！");
                        if (user.getGrade() < 30){
                            System.out.println("很可惜，您目前等级不足，无法上前挑战~");
                            return;
                        }
                        if (user.getDefense() >= 80 && user.getAttack() >= 150){
                            System.out.println("成功击杀守卫将军！！获得等级提升 + 2、攻击提升 + 20、防御提升 + 15、灵力提升 + 5");
                            user.setGrade(user.getGrade() + 2);
                            user.setAttack(user.getAttack() + 20);
                            user.setDefense(user.getDefense() + 15);
                            user.setMana(user.getMana() + 5);
                            return;
                        }
                        if (user.getDefense() >= 80 || user.getAttack() >= 150){
                            System.out.println("成功侥幸击杀了阴阳小镇守卫将军，过程坎坷，受了点伤。血量 - 30、等级提升 + 2、攻击提升 + 15、防御提升 + 10、灵力提升 + 2");
                            user.setBlood(user.getBlood() - 30);
                            user.setGrade(user.getGrade() + 2);
                            user.setAttack(user.getAttack() + 15);
                            user.setDefense(user.getDefense() + 10);
                            user.setMana(user.getMana() + 2);
                            return;
                        }
                    }
                    break mmp;
                case 4: // 前往武士城探险
                    if (r == 1){
                        System.out.println("探险过程中，感叹路边的路人有着丰富的武器装备，不争气的口水从眼角流出~");
                        return;
                    }
                    if (r == 2){
                        while (true) {
                            System.out.print("前方正在进行比武，是否进入？（Y\\N）：");
                            String choice = scanner.next();
                            if (choice.equals("Y") || choice.equals("y")){
                                System.out.println("你选择了迎战！");
                                System.out.println("对不起，多用户PK在第一版本中以纯SE无以手段实现，主要对于萌新的角度来讲是不便于实现\n因为这当中将涉及到多线程以及TCP\\IP协议相关知识点~为了萌新学习体验，不便第一版本中开发，敬请谅解~");
                                return;
                            }else if (choice.equals("N") || choice.equals("n")){
                                System.out.println("比赛非常激烈，你在一旁看完了全过程。等级 + 1");
                                user.setGrade(user.getGrade() + 1);
                                return;
                            }else{
                                System.out.println("您的选择不正确，请重新输入~");
                            }
                        }
                    }
                    if (r == 3){
                        System.out.print("你路过了一个武器店，");
                        if (user.getGold() < 50){
                            System.out.println("但是很可惜，您的金币不足，无法购买武器~");
                            return;
                        }
                        System.out.print("请问是否进行购买武器以提升自身攻击？（Y\\N）：");
                        while (true) {
                            String choice = scanner.next();
                            if (choice.equals("Y") || choice.equals("y")){
                                System.out.println("您成功购买了一把武器、消费了 50 金币");
                                user.setGold(user.getGold() - 50);
                                user.setAttack(user.getAttack() + 30);
                                return;
                            }else if (choice.equals("N") || choice.equals("n")){
                                System.out.println("你离开了武器店~");
                                return;
                            }else{
                                System.out.println("您的选择不正确，请重新输入~");
                            }
                        }
                    }
                    if (r == 4){
                        System.out.println("什么都没有发生~");
                        return;
                    }
                    break mmp;
                case 5: // 前往邪恶城堡探险 - 前期不予开发。敬请谅解
                    if (r == 1){
                        System.out.println("");
                    }
                    if (r == 2){
                        System.out.println("");
                    }
                    if (r == 3){
                        System.out.println("");
                    }
                    if (r == 4){
                        System.out.println("");
                    }
                    break mmp;
                default:
                    System.out.println("请重新输入：");
            }
        }
    }

    /**
     * 修改账户密码
     * @param scanner 键盘扫描器
     * @param user 当前已登录的用户
     */
    private static void changePassword(Scanner scanner,User user,SHA256 sha256){
        // 定义正则表达式字符串
        String s = "^(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9~!@&%#_]{8,}$";
        // 编译正则表达式
        Pattern pattern = Pattern.compile(s);

        System.out.print("请输入原密码：");
        String oldPassword = scanner.next();
        scanner = new Scanner(System.in); // 这大概是清空缓冲区最佳的办法
        // 获取用户输入的原密码的散列值
        oldPassword = sha256.SHA256encryption(oldPassword);
        if (oldPassword.equals(user.getPassword())){
            System.out.print("请输入新密码：");
            String password = scanner.next();
            Matcher matcher = pattern.matcher(password); // 将密码与正则表达式进行匹配
            while(true){
                if (matcher.matches() == false){
                    System.out.println("对不起，您输入的密码不安全，请更改为最少长度为8且最少包含一个大写字母和小写字母！");
                }
                if (matcher.matches() == true){
                    break; // 跳出死循环
                }
            }
            System.out.print("确认密码：");
            scanner = new Scanner(System.in);
            String okPassword = scanner.next();
            if (password.equals(okPassword)){
                // 将密码进行加密
                okPassword = sha256.SHA256encryption(okPassword);
                user.setPassword(okPassword);
                user.setEncryption("SHA-256"); // 将用户密码加密格式修改为当前最新加密方式
                // 将内存中的password内存区清空 顺带请求一次垃圾清理
                // 创建弱引用，并让此引用到密码的字符串
                var stringPassword = new WeakReference(password);
                var stringOkPassword = new WeakReference(okPassword);
                var stringOldPassword = new WeakReference(oldPassword);
                oldPassword = null;
                password = null;
                okPassword = null;
                System.gc();
                System.runFinalization();
                System.out.println("密码修改成功，请牢记您的新密码~");
            }
        }else{
            System.out.println("对不起，您的身份有误请重新核对密码~");
        }
    }

    private static void SystemArmsShop(ArrayList<Arms> armsArrayList,User user){
        boolean length = false; // 如果整个商店都没有上架的商品则为false
        if (armsArrayList == null){
            System.err.println("警告：SystemArmsShop方法传入空值！系统自动终结对应方法执行！");
            return;
        }
        // 判断当前武器商店是否有商品
        if (armsArrayList.size() == 0){
            System.out.println("当前系统武器商店中不存在任何商品，请添加后查看。");
            return; // 终结方法
        }
        // 判断是商城中有商品但是都未上架以防止一个商品都没打印却让用户输入要购买的武器的情况
        for (Arms arms : armsArrayList) {
            if (arms.getState()){
                length = true; // 证明有上架的商品
                break; // 已经不需要继续循环下去了，防止浪费系统资源
            }
        }
        // 判断商品上架总数是否大于等于1
        if (length == false){
            System.out.println("对不起，武器商店中不存在任何商品或已有商品但是未上架，请进行检查！");
            return; // 若length为true则进入if，需要立即退出执行该方法
        }
        // 循环遍历集合中元素
        for (Arms arms : armsArrayList) {
            // 判断当前遍历的商品是否为上架状态
            if (arms.getState()){
                ShopArms shopArms = new ShopArms();
                shopArms.getArms(arms); // 打印商品信息
            }
        }
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入您要购买的武器名称：");
        String armsName = scanner.next();
        for (Arms arms : armsArrayList) {
            if (arms.getName().equals(armsName))
            {
                System.out.println("您要购买的武器为：" + arms.getName() + "。您将花费金币：" + arms.getMoney());
                System.out.println("请确认是否购买(Y/N)：");
                scanner = new Scanner(System.in);
                String confirm = scanner.next();
                if (confirm.equals("Y") || confirm.equals("y")){
                    // 判断用户余额是否足够
                    if (user.getGold() < arms.getMoney()){
                        System.out.println("对不起，您的余额不足，请继续努力冒险赚钱去吧！");
                        return; // 终结方法
                    }else{
                        user.setGold(user.getGold() - arms.getMoney());
                        user.setAttack(user.getAttack() + arms.getAttack());
                        user.setWeaponBar(arms);
                        System.out.println("恭喜您，您成功的购买了【" + arms.getName() + "】花费了：" + arms.getMoney() + "金币");
                        return; // 终结方法
                    }
                }else{
                    System.out.println("欢迎您下次到来 ~");
                    return;
                }
            }
            System.out.println("看来找了一圈都没有找到您想要的商品呢，请您想好再来哦~");
        }
        return;
    }
}
